/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.                                     
 */
package jp.ize.ux.utils;

// {{{ enum RangeDir
enum RangeDir {
	Under;
	Over;
}
// }}}
// {{{ enum RangeState
enum RangeState {
	Include;
	InRange( dir:RangeDir );
	OutOfRange( dir:RangeDir );
	Exclude;
}
// }}}
// {{{ class UXRange
/** 
 * UXRangeクラス。<br>
 * 値の範囲を表現するクラス。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id: UXRange.hx 20 2009-02-04 08:23:19Z yimai.v $<br>
 */
class UXRange
{
	// {{{ public var min(default, default) : Float;
	/**
	 * 最小値
	 */
	public var min(default, default) : Float;
	// }}}
	// {{{ public var max(default, default) : Float;
	/**
	 * 最大値
	 */
	public var max(default, default) : Float;
	// }}}
	// {{{ public function new( ?min: Float, ?max: Float )
	/**
	 * コンストラクタ.
	 * デフォルトの最小値は-1.7976931348623158e+308、最大値は1.7976931348623158e+308.
	 */
	public function new( ?min: Float, ?max: Float )
	{
		if( min == null ) {
			min = 1.7976931348623158e+308;
		}
		if( max == null ) {
			max = -1.7976931348623158e+308;
		}
		this.min = min;
		this.max = max;
	}
	// }}}
	// {{{ public function distance() : Float
	/**
	* 最大値と最小値の差を取得します。
	*/
	inline public function distance() : Float
	{
		return this.max - this.min;
	}
	// }}}
	// {{{ public function rate( v:Float ) : Float
	/**
	* 指定した値が最小値から、どの位置にあるのか%パーセンテージにて返します。
	* 0 から 1 の値です。
	*/
	inline public function rate( v:Float ) : Float
	{
		return (v - this.min) / distance();
	}
	// }}}
	// {{{ public function spread( v : Float ) : Void
	/**
	* 値vによって最大値もしくは最大値を広げます。
	* 値vが最大値より小さく、最小値より大きければ、この関数は何もしません。
	*/
	public function spread( v : Float ) : Void
	{
		if( v < this.min ) { this.min = v; }
		if( v > this.max ) { this.max = v; }
	}
	// }}}
	// {{{ public function merge( r : UXRange ) : Void
	/**
	* 与えられた範囲の最小値と自身の最小値の小さい方、
	* 与えられた範囲の最大値と自身の最大値の大きい方を新しく自身の範囲とします。
	*/
	public function merge( r : UXRange ) : Void
	{
		this.min = Math.min( this.min, r.min );
		this.max = Math.max( this.max, r.max );
	}
	// }}}
	// {{{ public function inValue( val:Float ) : Bool
	/**
	* 与えられた値が範囲内にあるかどうかを返します
	*/
	inline public function inValue( val:Float ) : Bool
	{
		if ( val>=min && val<=max ) {
			return true;
		} else {
			return false;
		}
	}

	// }}}
	// {{{ public function outValue( val:Float ) : Bool
	/**
	* 与えられた値が範囲外であるかどうかを返します
	*/
	inline public function outValue( val:Float ) : Bool
	{
		if ( val>=min && val<=max ) {
			return false;
		} else {
			return true;
		}
	}

	// }}}
	// {{{ public function inRange( r:UXRange ) : Bool
	/**
	* 与えられたUXRangeが範囲内にあるかどうかを返します
	*/
	inline public function inRange( r:UXRange ) : Bool
	{
		if ( r.min>=min && r.max<=max ) {
			return true;
		} else {
			return false;
		}
	}

	// }}}
	// {{{ public function outRange( r:UXRange ) : Bool
	/**
	* 与えられたUXRangeが範囲内にあるかどうかを返します
	*/
	inline public function outRange( r:UXRange ) : Bool
	{
		if ( r.min>=min && r.max<=max ) {
			return true;
		} else {
			return false;
		}
	}

	// }}}
	// {{{ public function compare( r:UXRange ) : RangeState
	/**
	* 与えられたUXRangeと比べます
	* OutOfRange( Uner ) : r.maxがminよりも小さい場合
	* InRange( Under )   : r.minはminよりも小さいが、r.maxがminよりも大きい場合
	* Include            : r.minはminよりも大きく、r.maxがmaxよりも小さい場合
	* InRange( Over )    : r.minがminよりも大きく、r.maxがmaxよりも大きい場合
	* OutOfRange( Over ) : r.minがmaxよりも大きい場合
	* Exclude            : r.minがminより小さく、r.maxがmaxより大きい場合
	*/
	inline public function compare( r:UXRange ) : RangeState
	{
		if ( r.max<min ) {
			return OutOfRange(Under);
		} else if ( r.min<min && r.max>=min && r.max<=max ) {
			return InRange(Under);
		} else if ( r.min>=min && r.max<=max ) {
			return Include;
		} else if ( r.min>=min && r.max>max && r.min<=max ) {
			return InRange(Over);
		} else if ( r.min>max ) {
			return OutOfRange(Over);
		} else {
			return Exclude;
		}
	}

	// }}}
}
// }}}
